package controller

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"log"
	"os"
)

// 将PEM格式的私钥字符串转换为*rsa.PrivateKey
func pemStringToPrivateKey(pemStr string) (*rsa.PrivateKey, error) {
	// 解码PEM块
	block, _ := pem.Decode([]byte(pemStr))
	if block == nil || block.Type != "PRIVATE KEY" {
		return nil, fmt.Errorf("failed to decode PEM block containing private key")
	}

	// 解析PKCS#1或PKCS#8格式的私钥
	privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		// 如果不是PKCS#8格式，尝试解析PKCS#1格式
		privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
		if err != nil {
			return nil, fmt.Errorf("failed to parse private key: %v", err)
		}
	}

	// 类型断言为*rsa.PrivateKey
	rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
	if !ok {
		return nil, fmt.Errorf("not an RSA private key")
	}

	return rsaPrivateKey, nil
}

// 生成PKCS #8格式的私钥
func generatePKCS8PrivateKey(bits int) (*rsa.PrivateKey, error) {
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return nil, err
	}

	// 将私钥编码为PKCS #8格式
	privDer, _ := x509.MarshalPKCS8PrivateKey(privateKey)

	// 这里通常会将privDer保存到文件或数据库中，但为了示例我们直接返回私钥对象
	// 如果需要PEM格式字符串，可以使用下面的代码将其转换为PEM

	privBlock := &pem.Block{
		Type:  "PRIVATE KEY",
		Bytes: privDer,
	}
	privPem := string(pem.EncodeToMemory(privBlock))
	log.Println(privPem)
	key, err := pemStringToPrivateKey(privPem)
	if err != nil {
		return nil, err
	}
	return key, nil
}

// 从PKCS #8私钥中提取公钥
func extractPublicKey(privateKey *rsa.PrivateKey) *rsa.PublicKey {
	return &privateKey.PublicKey
}

// 将公钥编码为PKIX格式（通常用于X.509证书和SSL/TLS）
func encodePublicKeyToPKIX(publicKey *rsa.PublicKey) ([]byte, error) {
	return x509.MarshalPKIXPublicKey(publicKey)
}

// 将PKIX格式的公钥编码为PEM格式
func encodePublicKeyToPEM(publicKeyBytes []byte) string {
	pubBlock := &pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: publicKeyBytes,
	}
	return string(pem.EncodeToMemory(pubBlock))
}

// LoadPrivateKeyFromPEMFile loads an RSA private key from a PEM file
func LoadPrivateKeyFromPEMFile(filePath string) (*rsa.PrivateKey, error) {
	// Read the PEM file
	pemData, err := ioutil.ReadFile(filePath)
	if err != nil {
		return nil, err
	}

	// Decode the PEM block
	block, _ := pem.Decode(pemData)
	if block == nil || block.Type != "RSA PRIVATE KEY" {
		return nil, errors.New("failed to decode PEM block containing RSA private key")
	}

	// Parse the private key
	privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	return privateKey.(*rsa.PrivateKey), nil
}
func Test(c *gin.Context) {
	// Path to the PEM file containing the private key
	privateKeyPath := "private_key.pem"

	// Load the private key from the PEM file
	privateKey, err := LoadPrivateKeyFromPEMFile(privateKeyPath)
	if err != nil {
		log.Fatalf("Error loading private key: %v", err)
	}

	// Data to be signed

	// 签名示例（使用SHA-256哈希算法）
	data := gin.H{
		"id_card":   "11111",
		"card_type": 2,
		"name":      "333",
	}
	message, err := json.Marshal(data)
	if err != nil {
		return
	}
	//message := []byte("This is a secret message")
	hash := sha256.Sum256(message)
	signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
	// 将签名转换为十六进制字符串
	signatureHex := hex.EncodeToString(signature)
	log.Println(signatureHex)

	if err != nil {
		fmt.Fprintf(os.Stderr, "Error signing message: %v\n", err)
		os.Exit(1)
	}
	// 提取公钥
	publicKey := extractPublicKey(privateKey)
	pemString := publicKeyToPEM(publicKey)

	log.Println(pemString)
	// 验签示例
	err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash[:], signature)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error verifying signature: %v\n", err)
		os.Exit(1)
	}

	fmt.Println("Signature verified successfully!")
}

func publicKeyToPEM(pubKey *rsa.PublicKey) string {
	pubKeyBytes, _ := x509.MarshalPKIXPublicKey(pubKey)
	pubKeyPEM := pem.EncodeToMemory(&pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: pubKeyBytes,
	})
	return string(pubKeyPEM)
}
